package com.syq.listener;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rabbitmq.client.Channel;
import com.syq.config.DelayedConfig;
import com.syq.constant.CacheConstants;
import com.syq.constant.RabbitMQConstants;
import com.syq.constant.StrategyConstants;
import com.syq.feign.CacheFeign;
import com.syq.model.StandardReport;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;

/**
 * @ClassName: RabbitMqListener
 * @Description: TODO
 * @Create by: syq
 * @Date: 2022/8/29 11:49
 */
@Slf4j
@Component
public class RabbitMqListener {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private CacheFeign cacheFeign;

    private Integer[] sendTTL = {0, 10000, 30000, 60000, 300000};

    @RabbitListener(queues = RabbitMQConstants.TOPIC_PUSH_SMS_REPORT)
    public void receiveMessagePushReport(Channel channel, Message message, StandardReport standardReport){
        //获取客户url地址
        try {
            String key = CacheConstants.CACHE_PREFIX_CLIENT+standardReport.getClientID();
            String httpUrl = cacheFeign.hget(key, "receivestatusurl");
            if (!StringUtils.isEmpty(httpUrl)){
                //开始推送状态报告
                //
                standardReport.setReceiveStatusUrl(httpUrl);
                //第一次发送
                standardReport.setSendCount(1);
                //设置发送状态
                standardReport.setState(1);
                String result=sendReport(standardReport);
            }else {
                log.info("[接口模块 - 状态报告推送] 用户不需要推送状态报告!, 流程执行完毕!"+objectMapper.writeValueAsString(standardReport));
            }
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private String sendReport(StandardReport standardReport) {
        //请求实体对象
        try {
            HttpEntity httpEntity=new HttpEntity(standardReport);
            return restTemplate.postForObject(standardReport.getReceiveStatusUrl(), httpEntity, String.class);
        } catch (Exception e) {
          log.error("[接口模块 - 状态报告推送]推送报告给用户抛出了异常:{}",e.getMessage());
          delayedMessageHandler(standardReport);
        }
        return null;
    }

    //出了第一次都需要延迟消息
    public void delayedMessageHandler(StandardReport standardReport){
        rabbitTemplate.convertAndSend(DelayedConfig.DELAYED_EXCHANGE,DelayedConfig.DELAYED_ROUTING_KEY,standardReport,message -> {
            //设置延迟消息的时间 局部设置时间 单位是毫秒
            message.getMessageProperties().setDelay(sendTTL[standardReport.getSendCount()]);
            return message;
        });

    }

    //接收延迟消息队列  第二次~第五次
    @RabbitListener(queues = DelayedConfig.DELAYED_QUEUE)
    public void recevierDelayedMessage(Channel channel, Message message, StandardReport standardReport){
        try {
            String receiveStatusUrl = standardReport.getReceiveStatusUrl();
            int sendCount = standardReport.getSendCount();
            if (sendCount>=5){
                standardReport.setState(2);
                log.error("[接口模块 - 状态报告推送]推送5次全失败:{}"+objectMapper.writeValueAsString(standardReport));
                channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
                return;
            }
            standardReport.setSendCount(sendCount+1);
            sendReport(standardReport);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}
